<?php
header("Content-Type: text/html; charset=utf-8");
/**
 * 微信支付帮助库
 * ====================================================
 * 接口分三种类型：
 * 【请求型接口】--Wxpay_client_
 * 		统一支付接口类--UnifiedOrder
 * 		订单查询接口--OrderQuery
 * 		退款申请接口--Refund
 * 		退款查询接口--RefundQuery
 * 		对账单接口--DownloadBill
 * 		短链接转换接口--ShortUrl
 * 【响应型接口】--Wxpay_server_
 * 		通用通知接口--Notify
 * 		Native支付——请求商家获取商品信息接口--NativeCall
 * 【其他】
 * 		静态链接二维码--NativeLink
 * 		JSAPI支付--JsApi
 * =====================================================
 * 【CommonUtil】常用工具：
 * 		trimString()，设置参数时需要用到的字符处理函数
 * 		createNoncestr()，产生随机字符串，不长于32位
 * 		formatBizQueryParaMap(),格式化参数，签名过程需要用到
 * 		getSign(),生成签名
 * 		arrayToXml(),array转xml
 * 		xmlToArray(),xml转 array
 * 		postXmlCurl(),以post方式提交xml到对应的接口url
 * 		postXmlSSLCurl(),使用证书，以post方式提交xml到对应的接口url
*/
	include_once("SDKRuntimeException.php");
	include_once("WxPay.config.php");
	use Wxpaym\WxPayConf_pub;
/**
 * 所有接口的基类
 */
class Common_util_pub
{
	/**
	 * 	作用：产生随机字符串，不长于32位
	 */
	public function createNoncestr( $length = 32 )
	{
		$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
		$str ="";
		for ( $i = 0; $i < $length; $i++ )  {
			$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
		}
		return $str;
	}

    /**
	 * 签名方法
     * @param array $Params 参数集合
     * @return string
     */
	public function getSign($Params)
	{
		//签名步骤一：按字典序排序参数
		ksort($Params);
		//签名步骤二：在$Parameters后加入KEY
		$String = http_build_query($Params)."&key=".WxPayConf_pub::KEY;
        $String = urldecode($String);//防止中文转义
		//签名步骤三：MD5加密
		$String = md5($String);
		//签名步骤四：所有字符转为大写
		$result_ = strtoupper($String);
		return $result_;
	}

    /**
	 * //生明请求参数
     * @param $ro_id  商户订单号
     * @param $money  标价金额
     * @param $pid    商品ID
     * @return array
     */
   public function  apiParam($ro_id,$money){
       $apiParam =[
           'appid'        =>WxPayConf_pub::APPID,          //公众账号ID
           'mch_id'       =>WxPayConf_pub::MCHID,          //商户号
           'nonce_str'    =>$this->createNoncestr(),       //随机字符串
           'body'          =>'茶叶商城',                   //商品描述
           'out_trade_no' =>$ro_id,                        //商户订单号
           'spbill_create_ip'=>$_SERVER['SERVER_ADDR'],  //终端IP
           'notify_url'       =>WxPayConf_pub::NOTIFY_URL,//通知地址
           'total_fee'        =>$money*100,                    //标价金额
       ];
       return $apiParam;
   }
    /**
	 * 统一下单（PC端）
     * @param $or_id  商户订单号
     * @param int $price  标价金额(分)
     * @param $com_id   商品ID
     * @return bool
     */
	public function getUrl($ro_id,$money){
		//1.生明请求参数
        $apiParam=$this->apiParam($ro_id,$money);

        $apiParam['trade_type'] ='NATIVE'; //交易类型
        $apiParam['product_id'] =10; //交易类型
        $apiParam['sign'] =$this->getSign($apiParam);
        //2.将数据转化为xml
		 $xml =$this->arrayToXml($apiParam);
		//3.发送请求
		$str = $this->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder');
		$arr = $this->xmlToArray($str);
		//4.判断
		if($arr['return_code'] == 'SUCCESS'){
//            dump($arr['code_url']);die();
            require_once EXTEND_PATH.'phpqrcode.php';//引入
            \QRcode::png($arr['code_url'],false,'L', 5);
            exit();
		}else{
			file_put_contents(RUNTIME_PATH.'http_request_error.txt',$str);
			return false;
		}
	}
    /**
     * 统一下单（手机网页端）
     * @param $or_id  商户订单号
     * @param int $price  标价金额(分)
     * @return bool
     */
    public function getUrl2($ro_id,$money){
        $scene_info ='{"h5_info":"h5_info" {"type": "Wap","wap_url":'.WxPayConf_pub::WAP_URL.'"wap_name":'.WxPayConf_pub::WAP_NAME.'}}';
        //1.生明请求参数
        $apiParam=$this->apiParam($ro_id,$money);
        $apiParam['scene_info'] =$scene_info; //场景信息
        $apiParam['trade_type'] ='MWEB'; //交易类型
        $apiParam['sign'] =$this->getSign($apiParam);
        //2.将数据转化为xml
        $xml =$this->arrayToXml($apiParam);
        //3.发送请求
        $str = $this->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder');
        $arr = $this->xmlToArray($str);
        //4.判断
        if($arr['return_code'] == 'SUCCESS'){
            return  $arr['mweb_url']; //返回支付跳转链接
        }else{
            file_put_contents(RUNTIME_PATH.'http_request_error.txt',$str);
            return false;
        }
    }
    /**
     * 统一下单（公众号端）
     * @param $or_id  商户订单号
     * @param int $price  标价金额(分)
     * @param $openid   用户认证
     * @return bool
     */
    public function getUrl3($ro_id,$money,$openid){
        //1.生明请求参数
        $apiParam=$this->apiParam($ro_id,$money);
        $apiParam['trade_type'] ='JSAPI'; //交易类型
        $apiParam['openid'] =$openid; //用户认证
        $getSign=$this->getSign($apiParam);//签名
        $apiParam['sign'] =$getSign;
        //2.将数据转化为xml
        $xml =$this->arrayToXml($apiParam);
        //3.发送请求
        $str = $this->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder');
        $arr = $this->xmlToArray($str);
        //4.判断
        if($arr['return_code'] == 'SUCCESS'){
            $parameters= $this->getParameters( $arr['prepay_id']);
            return $parameters;
        }else{
            file_put_contents(RUNTIME_PATH.'http_request_error.txt',$str);
            return false;
        }
    }

    /**
     * 	作用：设置jsapi的参数
     */
    public function  getParameters($prepay_id)
    {
        $jsApiObj["appId"] = WxPayConf_pub::APPID;
        $timeStamp = time();
        $jsApiObj["timeStamp"] = "$timeStamp";
        $jsApiObj["nonceStr"] = $this->createNoncestr();
        $jsApiObj["package"] ='prepay_id='.$prepay_id;
        $jsApiObj["signType"] = "MD5";
        $jsApiObj["paySign"] = $this->getSign($jsApiObj);
        return $jsApiObj;
    }

	/**
	 * 	作用：array转xml
	 */
	public  function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        {
        	 if (is_numeric($val))
        	 {
        	 	$xml.="<".$key.">".$val."</".$key.">";

        	 }
        	 else{
				 $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
			}

        }
        $xml.="</xml>";
        return $xml;
    }

	/**
	 * 	作用：将xml转为array
	 */
	public  function xmlToArray($xml)
	{
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		return $array_data;
	}

	/**
	 * 	作用：以post方式提交xml到对应的接口url
	 */
	public function postXmlCurl($xml,$url,$second=30)
	{

        //初始化curl
       	$ch = curl_init();
		//设置超时
		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
		//设置header
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		//要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		//post提交方式
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
		//运行curl
        $data = curl_exec($ch);
		//curl_close($ch);
		//返回结果

		if($data)
		{
			curl_close($ch);
			return $data;
		}
		else
		{
			$error = curl_errno($ch);
			echo "curl出错，错误码:$error"."<br>";
			echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
			curl_close($ch);
			return false;
		}
	}

	/**
	 * 	作用：使用证书，以post方式提交xml到对应的接口url
	 */
	function postXmlSSLCurl($xml,$url,$second=30)
	{
		$ch = curl_init();
		//超时时间
		curl_setopt($ch,CURLOPT_TIMEOUT,$second);
		//这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
		//设置header
		curl_setopt($ch,CURLOPT_HEADER,FALSE);
		//要求结果为字符串且输出到屏幕上
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
		//设置证书
		//使用证书：cert 与 key 分别属于两个.pem文件
		//默认格式为PEM，可以注释
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
//		curl_setopt($ch,CURLOPT_SSLCERT, WxPayConf_pub::SSLCERT_PATH);
        curl_setopt($ch,CURLOPT_SSLCERT, EXTEND_PATH . 'WxminiPayPubHelper/cacert/apiclient_cert.pem');
		//默认格式为PEM，可以注释
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
//		curl_setopt($ch,CURLOPT_SSLKEY, WxPayConf_pub::SSLKEY_PATH);
        curl_setopt($ch,CURLOPT_SSLKEY, EXTEND_PATH . 'WxminiPayPubHelper/cacert/apiclient_key.pem');
		//post提交方式
		curl_setopt($ch,CURLOPT_POST, true);
		curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
		$data = curl_exec($ch);
		//返回结果
		if($data){
			curl_close($ch);
			return $data;
		}
		else {
			$error = curl_errno($ch);
			echo "curl出错，错误码:$error"."<br>";
			echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
			curl_close($ch);
			return false;
		}
	}

	/**
	 * 	作用：打印数组
	 */
	function printErr($wording='',$err='')
	{
		print_r('<pre>');
		echo $wording."</br>";
		var_dump($err);
		print_r('</pre>');
	}
}

?>